#include <iostream>
#include <opencv2/opencv.hpp>

using namespace std;

void gaussianNoise (const cv::Mat &input, cv::Mat &output);

int main(int argc, char **argv)
{
  CV_Assert (argc > 1);

  cv::Mat origin = cv::imread (argv[1], cv::IMREAD_GRAYSCALE);

  cv::Mat noise;
  gaussianNoise(origin, noise);

  cv::Mat gauss;
  cv::GaussianBlur(noise, gauss, cv::Size(3, 3), 50);

  cv::Mat bilateral;
  cv::bilateralFilter(noise, bilateral, 9, 50, 150);

  // Save
  cv::imwrite("origin.png", origin);
  cv::imwrite("noise.png", noise);
  cv::imwrite("gauss.png", gauss);
  cv::imwrite("bilateral.png", bilateral);

  // Display
  cv::imshow("origin", origin);
  cv::imshow("noise", noise);
  cv::imshow("gauss", gauss);
  cv::imshow("bilateral", bilateral);

  cv::waitKey();

  return 0;
}

void gaussianNoise (const cv::Mat &input, cv::Mat &output)
{
  cv::Mat noise(input.size(), input.type());
  cv::randn(noise, 0, 30);
  cv::add(input, noise, output);
}
